<!--
 * @Author: 杨湲 yy7072@qq.com
 * @Date: 2025-09-11 16:31:18
 * @LastEditors: 杨湲 yy7072@qq.com
 * @LastEditTime: 2025-10-07 11:17:01
 * @FilePath: \city\src\pages\components(1)\Bottom4.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <!-- 组件根容器：包裹标题和图表 -->
  <div>
    <!-- 引入自定义标题组件：通过props动态传入图表标题 -->
    <Title :title="title"></Title>

    <!-- 散点图渲染容器：
      1. ref="bottom2"：给容器标记唯一标识，供脚本通过$refs获取DOM元素
      2. 内联样式：固定高度150px（确保图表有稳定渲染空间），顶部margin30px（与标题拉开距离，避免拥挤）
    -->
    <div ref="bottom2" style="height: 150px;margin-top: 30px;"></div>
  </div>
</template>

<script>
// 1. 引入AntV G2Plot的散点图组件：核心可视化工具，用于绘制散点和回归线
import { Scatter } from '@antv/g2plot';
// 2. 引入项目封装的HTTP请求工具：用于调用后端接口获取监测数据
import { get } from '@/utils/request';
// 3. 引入moment时间格式化工具：处理后端返回的时间戳，转为易读格式
import moment from 'moment';
// 4. 引入Vuex的mapState辅助函数：从全局状态中获取设备信息（ed）
import { mapState } from 'vuex';

export default {
  // 组件数据定义：存储组件内部状态
  data() {
    return {
      title: '噪音回归线', // 图表标题：传给Title组件展示
      // 接口请求参数：用于筛选后端返回的监测数据
      params: {
        page: 3, // 页码：默认请求第3页数据
        pageSize: 300 // 每页条数：一次获取300条，保证数据量足够支撑回归线分析
      },
      zData: [], // 处理后的噪声数据数组：最终传给散点图的数据源
      scatter: null // 散点图实例对象：存储图表实例，便于后续更新数据（避免重复创建）
    };
  },
  // 计算属性：映射Vuex全局状态到组件内部
  computed: {
    // ...mapState(['ed'])：将Vuex中名为ed的状态（通常存储设备ID、工程ID等）映射为组件属性
    ...mapState(['ed'])
  },
  // 监听器：监听Vuex中ed状态的变化，实现数据联动
  watch: {
    // 监听ed状态（设备信息）
    ed: {
      // 状态变化时执行的回调函数：n=新状态，o=旧状态
      handler(n, o) {
        // 1. 更新请求参数：将新设备的ID（engineer_id/device_id）传入params，确保请求对应设备的数据
        this.params.engineer_id = n.engineer_id;
        this.params.device_id = n.device_id;
        // 2. 重新调用接口获取新设备的噪声数据
        this.getZData();
        // 3. 用新数据更新图表：通过scatter实例的changeData方法，避免重新创建图表（提升性能）
        this.scatter.changeData(this.zData);
      },
      // 深度监听：若ed是对象（含多个属性，如engineer_id/device_id），其内部属性变化也会触发监听
      deep: true
    }
  },
  // 组件方法：封装业务逻辑（图表渲染、数据获取）
  methods: {
    /**
     * 渲染散点图和回归线的方法
     * 作用：初始化散点图实例，配置图表样式和数据，最终渲染到DOM
     */
    loadScatter() {
      // 1. 创建散点图实例：参数1=图表容器（通过$refs获取），参数2=图表配置项
      this.scatter = new Scatter(this.$refs.bottom2, {
        data: this.zData, // 数据源：绑定处理后的zData
        xField: 'insert_time', // X轴字段：对应数据中的时间字段（格式化后的"HH:mm"）
        yField: 'noise', // Y轴字段：对应数据中的噪声值字段（核心监测指标）
        size: 5, // 散点大小：5px（避免过小看不见或过大拥挤）
        // 散点样式配置：控制散点的外观
        pointStyle: {
          stroke: 'green', // 散点边框颜色：绿色
          lineWidth: 1, // 边框宽度：1px
          fill: 'pink', // 散点填充色：粉色（高辨识度，便于区分）
        },
        // 回归线配置：核心分析功能，用于展示数据趋势
        regressionLine: {
          type: 'quad', // 回归线类型：二次多项式回归（可选值：linear线性、exp指数、loess局部加权等）
        },
      });

      // 2. 渲染图表：将配置好的图表渲染到指定容器中
      this.scatter.render();
    },

    /**
     * 获取并处理噪声数据的方法（异步）
     * 作用：调用后端接口获取原始数据，格式化时间、降采样后存入zData
     */
    async getZData() {
      // 1. 调用后端接口：通过get工具请求数据，参数1=接口地址，参数2=请求参数（params）
      // 注意：此处接口地址后多了"?"，实际请求时可能拼接多余字符，建议改为'/dashboard/pageQueryData'
      let res = await new get('/dashboard/pageQueryData?', this.params);
      // 2. 打印接口返回结果：用于开发调试，查看数据格式是否正确
      console.log(res, '84163');
      // 3. 临时数组temp：存储处理后的有效数据（避免直接修改原始数据）
      let temp = [];

      // 4. 遍历原始数据（res.data.list），进行格式化和筛选
      res.data.list.forEach((item, index, arr) => {
        // 临时硬编码：强制将第一条数据的noise设为34.8（可能用于处理第一条数据异常，建议后续改为动态判断）
        arr[0].noise = 34.8,
        // 时间格式化：将后端返回的时间戳（如item.insert_time）转为"HH:mm"（时分）格式，便于X轴展示
        item.insert_time = moment(item.insert_time).format("HH:mm");
        // 数据降采样：每隔10条数据取1条（避免原始数据过密导致散点重叠，影响视觉效果）
        if (index % 10 == 0) {
          temp.push(arr[index]); // 将筛选后的数据存入temp
        }
      });

      // 5. 将处理后的temp数组赋值给zData，供图表使用
      this.zData = temp;
    }
  },
  // 生命周期钩子：组件挂载完成后执行（DOM已渲染，可操作图表容器）
  async mounted() {
    // 1. 异步获取数据：等待getZData执行完成（确保数据加载后再渲染图表）
    await this.getZData();
    // 2. 渲染图表：数据就绪后，调用loadScatter初始化并渲染图表
    this.loadScatter();
  }
}
</script>

<!-- 组件样式：scoped表示样式仅作用于当前组件，避免污染全局 -->
<style lang="less" scoped>
/* 目前无自定义样式：预留扩展空间（如后续可添加容器阴影、标题样式等） */
</style>